package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.domain.R;
import com.comac.ins.common.core.exception.ServiceException;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.common.oss.core.OssClient;
import com.comac.ins.common.oss.entity.UploadResult;
import com.comac.ins.common.oss.factory.OssFactory;
import com.comac.ins.isfd.constant.enums.IsfdAcousticsTypeEnum;
import com.comac.ins.isfd.domain.IsfdAcousticsIsotropicSolidMaterial;
import com.comac.ins.isfd.domain.bo.IsfdAcousticsIsotropicSolidMaterialBo;
import com.comac.ins.isfd.domain.bo.query.IsfdAcousticsIsotropicSolidMaterialQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdAcousticsIsotropicSolidMaterialVo;
import com.comac.ins.isfd.mapper.IsfdAcousticsIsotropicSolidMaterialMapper;
import com.comac.ins.isfd.service.IIsfdAcousticsIsotropicSolidMaterialService;
import com.comac.ins.isfd.util.AcousticsMaterialFileParserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 声学固体材料Service业务层处理
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class IsfdAcousticsIsotropicSolidMaterialServiceImpl implements IIsfdAcousticsIsotropicSolidMaterialService {

    @Autowired
    private IsfdAcousticsIsotropicSolidMaterialMapper baseMapper;

    @Autowired
    private AcousticsMaterialFileParserUtil acousticsMaterialFileParserUtil;

    @Override
    public IsfdAcousticsIsotropicSolidMaterialVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }


    @Override
    public TableDataInfo<IsfdAcousticsIsotropicSolidMaterialVo> queryPageList(IsfdAcousticsIsotropicSolidMaterialQueryBo queryBo) {
        Integer pageNum = queryBo.getPageNum();
        Integer pageSize = queryBo.getPageSize();
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(pageNum);
        pageQuery.setPageSize(pageSize);
        LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> lqw = buildQueryWrapper(queryBo);
        Page<IsfdAcousticsIsotropicSolidMaterialVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public List<IsfdAcousticsIsotropicSolidMaterialVo> queryList(IsfdAcousticsIsotropicSolidMaterialBo bo) {
        LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> buildQueryWrapper(IsfdAcousticsIsotropicSolidMaterialQueryBo bo) {
        LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), IsfdAcousticsIsotropicSolidMaterial::getMaterialName, bo.getMaterialName());
        lqw.eq(bo.getPoissonRatioReal() != null, IsfdAcousticsIsotropicSolidMaterial::getPoissonRatioReal, bo.getPoissonRatioReal());
        lqw.eq(bo.getPoissonRatioImag() != null, IsfdAcousticsIsotropicSolidMaterial::getPoissonRatioImag, bo.getPoissonRatioImag());
        lqw.eq(bo.getSolidDensityReal() != null, IsfdAcousticsIsotropicSolidMaterial::getSolidDensityReal, bo.getSolidDensityReal());
        lqw.eq(bo.getSolidDensityImag() != null, IsfdAcousticsIsotropicSolidMaterial::getSolidDensityImag, bo.getSolidDensityImag());
        lqw.eq(bo.getYoungModulusReal() != null, IsfdAcousticsIsotropicSolidMaterial::getYoungModulusReal, bo.getYoungModulusReal());
        lqw.eq(bo.getYoungModulusImag() != null, IsfdAcousticsIsotropicSolidMaterial::getYoungModulusImag, bo.getYoungModulusImag());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitSystem()), IsfdAcousticsIsotropicSolidMaterial::getUnitSystem, bo.getUnitSystem());
        lqw.eq(StringUtils.isNotBlank(bo.getUrl()), IsfdAcousticsIsotropicSolidMaterial::getUrl, bo.getUrl());
        lqw.orderByDesc(IsfdAcousticsIsotropicSolidMaterial::getCreateTime);
        return lqw;
    }

    private LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> buildQueryWrapper(IsfdAcousticsIsotropicSolidMaterialBo bo) {
        LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getMaterialName()), IsfdAcousticsIsotropicSolidMaterial::getMaterialName, bo.getMaterialName());
        lqw.eq(bo.getPoissonRatioReal() != null, IsfdAcousticsIsotropicSolidMaterial::getPoissonRatioReal, bo.getPoissonRatioReal());
        lqw.eq(bo.getPoissonRatioImag() != null, IsfdAcousticsIsotropicSolidMaterial::getPoissonRatioImag, bo.getPoissonRatioImag());
        lqw.eq(bo.getSolidDensityReal() != null, IsfdAcousticsIsotropicSolidMaterial::getSolidDensityReal, bo.getSolidDensityReal());
        lqw.eq(bo.getSolidDensityImag() != null, IsfdAcousticsIsotropicSolidMaterial::getSolidDensityImag, bo.getSolidDensityImag());
        lqw.eq(bo.getYoungModulusReal() != null, IsfdAcousticsIsotropicSolidMaterial::getYoungModulusReal, bo.getYoungModulusReal());
        lqw.eq(bo.getYoungModulusImag() != null, IsfdAcousticsIsotropicSolidMaterial::getYoungModulusImag, bo.getYoungModulusImag());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitSystem()), IsfdAcousticsIsotropicSolidMaterial::getUnitSystem, bo.getUnitSystem());
        lqw.eq(StringUtils.isNotBlank(bo.getUrl()), IsfdAcousticsIsotropicSolidMaterial::getUrl, bo.getUrl());
        lqw.orderByDesc(IsfdAcousticsIsotropicSolidMaterial::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public R<Void> batchUploadMaterials(MultipartFile[] files) {
        if (files == null || files.length == 0 || files[0].isEmpty()) {
            return R.fail("请选择要上传的文件");
        }

        int successCount = 0;
        int failCount = 0;
        List<String> errorMessages = new ArrayList<>();

        OssClient storage = OssFactory.instance();
        for (MultipartFile file : files) {
            String currentFileError = null;

            try {
                // 检查文件类型
                String originalFilename = file.getOriginalFilename();
                if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".dat")) {
                    currentFileError = "跳过非dat文件: " + originalFilename;
                    log.error(currentFileError);
                    failCount++;
                    errorMessages.add(currentFileError);
                    continue;
                }

                // 解析文件内容
                Object parsedMaterial = acousticsMaterialFileParserUtil.parseMaterialFile(file);
                if (!(parsedMaterial instanceof IsfdAcousticsIsotropicSolidMaterial)) {
                    currentFileError = "文件不是固体材料: " + originalFilename;
                    log.error(currentFileError);
                    failCount++;
                    errorMessages.add(currentFileError);
                    continue;
                }

                IsfdAcousticsIsotropicSolidMaterial material = (IsfdAcousticsIsotropicSolidMaterial) parsedMaterial;

                // 检查材料是否已存在（基于属性组合）
                boolean exists = checkSolidMaterialExists(material, null);
                if (exists) {
                    currentFileError = "固体材料已存在，材料属性组合重复: " + " (文件: " + originalFilename + ")";
                    log.error(currentFileError);
                    failCount++;
                    errorMessages.add(currentFileError);
                    continue;
                }

                // 上传到OSS
                String filePath = IsfdAcousticsTypeEnum.ACOUSTICS.getValue() + "/" + IsfdAcousticsTypeEnum.ISOTROPIC_SOLID.getValue() + "/" + file.getOriginalFilename();
                UploadResult uploadResult;
                try {
                    uploadResult = storage.upload(file.getBytes(), filePath);
                } catch (IOException e) {
                    throw new ServiceException(e.getMessage());
                }
                material.setUrl(uploadResult.getUrl());

                // 保存到数据库
                baseMapper.insert(material);
                successCount++;
                log.info("成功上传固体材料: {}", material.getMaterialName());

            } catch (Exception e) {
                currentFileError = "上传固体材料文件失败: " + file.getOriginalFilename() + " - " + e.getMessage();
                log.error(currentFileError, e);
                failCount++;
                errorMessages.add(currentFileError);
            }
        }

        // 构建详细的消息
        StringBuilder messageBuilder = new StringBuilder();
        messageBuilder.append(String.format("上传完成: 成功 %d 个, 失败 %d 个", successCount, failCount));

        // 如果有失败的文件，添加详细错误信息
        if (!errorMessages.isEmpty()) {
            messageBuilder.append("\n\n失败详情:\n");
            for (int i = 0; i < errorMessages.size(); i++) {
                messageBuilder.append(i + 1).append(". ").append(errorMessages.get(i)).append("\n");
            }
        }

        String message = messageBuilder.toString();
        if (failCount > 0) {
            return R.fail(message);
        }
        return R.ok(message);
    }

    @Override
    public Boolean updateMaterial(IsfdAcousticsIsotropicSolidMaterialBo bo) {
        if (bo.getId() == null) {
            throw new BaseException("材料ID不能为空");
        }

        // 检查材料是否存在
        IsfdAcousticsIsotropicSolidMaterial existingMaterial = baseMapper.selectById(bo.getId());
        if (existingMaterial == null) {
            throw new BaseException("材料不存在");
        }

        // 检查属性组合是否与其他材料重复（排除自身）
        IsfdAcousticsIsotropicSolidMaterial updateMaterial = MapstructUtils.convert(bo, IsfdAcousticsIsotropicSolidMaterial.class);
        boolean exists = checkSolidMaterialExists(updateMaterial, bo.getId());
        if (exists) {
            throw new BaseException("材料属性组合已存在，请修改相关参数");
        }

        return baseMapper.updateById(updateMaterial) > 0;
    }

    @Override
    public Boolean addMaterial(IsfdAcousticsIsotropicSolidMaterialBo bo) {
        // 检查属性组合是否与其他材料重复（排除自身）
        IsfdAcousticsIsotropicSolidMaterial addMaterial = MapstructUtils.convert(bo, IsfdAcousticsIsotropicSolidMaterial.class);
        boolean exists = checkSolidMaterialExists(addMaterial, null);
        if (exists) {
            throw new BaseException("材料属性组合已存在，请修改相关参数");
        }
        return baseMapper.insert(addMaterial) > 0;
    }

    /**
     * 检查固体材料是否存在（基于属性组合）
     *
     * @param material  要检查的材料
     * @param excludeId 要排除的ID（用于更新操作）
     * @return 是否存在重复
     */
    private boolean checkSolidMaterialExists(IsfdAcousticsIsotropicSolidMaterial material, Long excludeId) {
        LambdaQueryWrapper<IsfdAcousticsIsotropicSolidMaterial> queryWrapper = Wrappers.lambdaQuery();

        // 构建精确查询条件
        queryWrapper.eq(IsfdAcousticsIsotropicSolidMaterial::getMaterialName, material.getMaterialName())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getPoissonRatioReal, material.getPoissonRatioReal())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getPoissonRatioImag, material.getPoissonRatioImag())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getSolidDensityReal, material.getSolidDensityReal())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getSolidDensityImag, material.getSolidDensityImag())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getYoungModulusReal, material.getYoungModulusReal())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getYoungModulusImag, material.getYoungModulusImag())
            .eq(IsfdAcousticsIsotropicSolidMaterial::getUnitSystem, material.getUnitSystem());

        // 如果是更新操作，排除自身
        if (excludeId != null) {
            queryWrapper.ne(IsfdAcousticsIsotropicSolidMaterial::getId, excludeId);
        }

        Long count = baseMapper.selectCount(queryWrapper);
        return count > 0;
    }
}
